package com.hh.core.aop;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import com.alibaba.fastjson.JSONObject;
import com.hh.core.annotion.OperationLog;
import com.hh.core.enums.OperationLogEnum;
import com.hh.core.log.LogManager;
import com.hh.core.log.LogTaskFactory;
import com.hh.core.log.LogTempObject;
import com.hh.core.shiro.entity.ShiroUser;
import com.hh.core.shiro.util.ShiroUtil;

/**
 * 
 * @ClassName: OperationLogAop
 * @Description: TODO(操作日志 aop)
 * @author hxn
 * @date 2018年2月9日 下午3:07:48
 *
 */
@Aspect
@Component
public class OperationLogAop {

	private static final Log log = LogFactory.get();

	@Pointcut(value = "@annotation(com.hh.core.annotion.OperationLog)")
	public void pointCut() {
	}

	@Around("pointCut()")
	public Object recordOperationLog(ProceedingJoinPoint point)
			throws Throwable {
		// 先执行业务
		Object result = point.proceed();
		try {
			handle(point);
		} catch (Exception e) {
			log.error(e,"日志记录出错!");
		}
		return result;
	}

	private void handle(ProceedingJoinPoint point) throws Exception {
		Signature sig = point.getSignature(); // 获取拦截的方法名
		MethodSignature msig = null;
		if (!(sig instanceof MethodSignature)) {
			throw new IllegalArgumentException("该注解只能用于方法");
		}
		// 如果当前用户未登录，不做日志
		ShiroUser user = ShiroUtil.getUser();
		if (ObjectUtil.isNull(user)) {
			return;
		}

		msig = (MethodSignature) sig;
		Object target = point.getTarget(); // 返回目标对象
		Method currentMethod = target.getClass().getMethod(msig.getName(),
				msig.getParameterTypes()); // 获取当前方法

		String className = point.getTarget().getClass().getSimpleName(); // 类名
		Object[] params = point.getArgs(); // 获取目标的调用参数
		// 获取操作注解
		OperationLog operationLog = currentMethod
				.getAnnotation(OperationLog.class);
		Integer type = operationLog.type().getCode();
		String name = operationLog.value();
		String method = currentMethod.getName();
		StringBuilder sb = new StringBuilder();
		boolean isNeed = false;
		if (operationLog.type().equals(OperationLogEnum.EDIT)) {//修改内容
			sb.append("{\"oldData\":");
			JSONObject json = new JSONObject();
			Object[] objectList = LogTempObject.me().getObject();
			for (Object object : objectList) {//循环获取旧的对象值
				json.put(object.getClass().getSimpleName(),object);
//				sb.append(BaseUtil.toOprLogStr(object));
			}
			sb.append(json.toJSONString()+",\"newData\":");
			isNeed = true;
		} else if (operationLog.type().equals(OperationLogEnum.DELETE)) {
			sb.append("{\""+operationLog.key() + "\":");
			isNeed = true;
		}
		JSONObject json = new JSONObject();
		if(params.length>0){
			int[] paramIndex = operationLog.paramIndex();
			for (int index : paramIndex) {//循环获取新的对象值
				json.put(params[index].getClass().getSimpleName(),params[index]);
			}
		}
		if(isNeed){
			sb.append(json.toJSONString()+"}");
		}else{
			sb.append(json.toJSONString());
		}
		String content = sb.toString();
		LogManager.me().executeLog(
				LogTaskFactory.operationLog(type, name, user.getId(),
						className, method, content));
	}
}
